/*!
 *  \file       test-parametric.cpp
 *  \brief      Main per testare un segnale di tipo \f$S_x = 1 + 2 \sqrt{ ( T^{ 2 } - t^{ 2 } ) }\f$
 *
 *  \author     Davide Scola <S2299453@studenti.unige.it>
 *  \author	Minetti Alberto <S3064777@studenti.unige.it>
 *  \version    1.0
 */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vector>
#include <iostream>

#include "IEntropyGenerator.hpp"
#include "TimeEntropyGenerator.hpp"
#include "DeviceEntropyGenerator.hpp"
#include "SmartEntropyGenerator.hpp"

#include "IRandomGenerator.hpp"
#include "SimpleRandomGenerator.cpp"
#include "NormalizedRandomGenerator.cpp"
#include "PoissonRandomGenerator.cpp"

#include "ISignalGenerator.hpp"	
#include "ParametricSignalGenerator.cpp"
#include "InputSignal.cpp"

#include "ISignalNoise.hpp"
#include "PoissonianNoise.cpp"
#include "MultiplicativeNoise.cpp"

#include "WrapNumber.cpp"
#include "RealNumber.hpp"


using namespace std;


// Generatore di entropia (globale cosi` che
// venga inizializzato una sola volta )
SmartEntropyGenerator entropy;


int
main( void )
{
  // genero un segnale parametrico
  ParametricSignalGenerator< RealNumber, PARAMETRIC_TVALUE > generator( PARAMETRIC_NPOINTS );
  InputSignal< RealNumber > clean( PARAMETRIC_NPOINTS, generator );
  
  // inizializzo il segnale "sporco"
  InputSignal< RealNumber > dirty( clean );
  PoissonianNoise< RealNumber> noise( entropy );
  
  dirty.addNoise( noise );
  
  unsigned long int iMax = clean.indexOfMax( );
  
  cout << "# Indice del massimo: " << iMax << endl;
  cout << "# clean[" << iMax << "] = " << clean[iMax] << endl;
  cout << "# dirty[" << iMax << "] = " << dirty[iMax] << endl;
  cout << "# Errore commesso: " << sqrt( dirty[iMax] ) / dirty[iMax] << endl;
  
  // correggo il segnale e ricalcolo il rumore
  RealNumber coeff = pow( 1 / PARAMETRIC_ERRMAX, 2 ) / clean[ clean.indexOfMax( ) ];
  cout << "# Fattore di correzione: " << coeff << endl;
  
  MultiplicativeNoise< RealNumber> correction( coeff );
  clean.addNoise( correction );
  
  dirty = clean;
  dirty.addNoise( noise );
  
  // visualizzo i risultati
  long double currPoint = -( long double )PARAMETRIC_TVALUE;
  long double step = 2.0 * ( long double )PARAMETRIC_TVALUE / PARAMETRIC_NPOINTS;
  
  for( unsigned long int i = 0; i < PARAMETRIC_NPOINTS; ++i, currPoint += step )
    cout << currPoint << " " << clean[i] << " " << dirty[i] << endl;
  
  return 0;
}
